package com.monas.server.transfer;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;

import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;

/**
 * Class SSH client to get access and result from command submitted.
 * 
 * @author eko wahyudi
 * 
 */
public class SSHClient {

	private final int port = 22;

	private InputStream inputStream = null;
	private PrintStream printStream = null;
	private ChannelShell channel = null;
	private Session session = null;

	private String endLineStr = "$";

	private boolean write = false;

	public SSHClient(String host, String user, String password)
			throws Exception {
		this(host, user, password, null);
	}

	public SSHClient(String host, String user, String password, String endLine)
			throws Exception {

		if (endLine != null) {
			endLineStr = endLine;
		}

		JSch shell = new JSch();

		// get a new session
		session = shell.getSession(user, host, port);

		// set user password and connect to a channel
		session.setUserInfo(new SSHUserInfo(password));
		session.connect();
		channel = (ChannelShell) session.openChannel("shell");
		channel.setInputStream(null);
		inputStream = channel.getInputStream();
		channel.connect();

		System.out.println("Connected into " + host + " with user:" + user);

		printStream = new PrintStream(channel.getOutputStream());
		readUntil();
	}

	/**
	 * Closing connection from SSH client.
	 * 
	 * @throws Exception
	 *             error
	 */
	public void disconnect() throws Exception {
		if (inputStream != null) {
			inputStream.close();
		}

		if (printStream != null) {
			printStream.close();
		}

		if (channel != null) {
			channel.disconnect();
		}

		if (session != null) {
			session.disconnect();
		}
	}

	/**
	 * Sending command into server.
	 * 
	 * @param command
	 *            command that submitted
	 * @return command result
	 * @throws Exception
	 *             error while send command
	 */
	public void sendCommand(String command) throws Exception {
		System.out.println("Send command : " + command);
		printStream.println(command);
		printStream.flush();
	}

	public String readUntil() throws IOException {
		return readUntil(endLineStr);
	}

	public String readUntil(String prompt) throws IOException {
		String line = "";
		char lastChar = prompt.charAt(prompt.length() - 1);

		StringBuffer buffer = new StringBuffer();
		char ch = (char) inputStream.read();
		while (true) {
			if (!write) {
				System.out.print(ch);
			}
			buffer.append(ch);

			if (ch == '\n') {
				line += buffer.toString();
				buffer.setLength(0);
			}

			if (ch == lastChar) {
				if (buffer.toString().endsWith(prompt)) {
					line += buffer.toString();
					buffer.setLength(0);
					break;
				}
			}

			ch = (char) inputStream.read();
		}
		return line;
	}

	public void setOnWrite(boolean write) {
		this.write = write;
	}

	/**
	 * This class implements JSCH UserInfo interface for passing password to the
	 * session.
	 */
	private class SSHUserInfo implements UserInfo {

		/**
		 * Password for user.
		 */
		private String password;

		/**
		 * SSH user information.
		 * 
		 * @param password
		 *            user password
		 */
		SSHUserInfo(String password) {
			this.password = password;
		}

		@Override
		public String getPassphrase() {
			return null;
		}

		@Override
		public String getPassword() {
			return password;
		}

		@Override
		public boolean promptPassword(String arg0) {
			return true;
		}

		@Override
		public boolean promptPassphrase(String arg0) {
			return true;
		}

		@Override
		public boolean promptYesNo(String arg0) {
			return true;
		}

		@Override
		public void showMessage(String arg0) {
			System.out.println(arg0);
		}
	}

}
